package com.jhgsys.internal.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Slf4j
public class BeanHelper {

    public static <T> T copyProperties(Object source, Class<T> target){
        try {
            T t = target.newInstance();
            BeanUtils.copyProperties(source, t);
            return t;
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换异常");
        }
    }

    public static <T> List<T> copyWithCollection(List<?> sourceList, Class<T> target){
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换异常");
        }
    }

    public static <T> Set<T> copyWithCollection(Set<?> sourceList, Class<T> target){
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toSet());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
            throw new RuntimeException("数据转换异常");
        }
    }

    static {
        ConvertUtils.register(new Converter(){
            @Override
            public Object convert(Class type, Object value) {
                Date date = null;
                String dateStr = (String)value;
                if (dateStr.length() > 10) {
                    date = DateUtil.parseDate(dateStr, "yyyy-MM-dd HH:mm:ss");
                } else {
                    date = DateUtil.parseDate(dateStr, "yyyy-MM-dd");
                }
                return date;
            }

        }, Date.class);
    }


    public static void setProperty(Object o, String prop, Object value) {
        try {
            prop = prop.toLowerCase();
            if (prop.indexOf(UNDERLINE) > 0) {
                prop = underlineToCamel(prop);
            }
            org.apache.commons.beanutils.BeanUtils.setProperty(o, prop, value);
        } catch (IllegalAccessException e) {
            log.error("Error in setProperty", e);
        } catch (InvocationTargetException e) {
            log.error("Error in setProperty", e);
        }
    }

    private static final char UNDERLINE='_';

    public static String camelToUnderline(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if (Character.isUpperCase(c)){
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String underlineToCamel(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if (c==UNDERLINE){
                if (++i<len){
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String getMethodName(String param) {
        if (param==null||"".equals(param.trim())){
            return "";
        }
        String ret = underlineToCamel(param);
        String sb = "set" +
                    Character.toUpperCase(ret.charAt(0)) +
                    ret.substring(1);
        return sb;
    }
}